﻿using FlexFlow.Base;
using FlexFlow.Base.File;
using FlexFlow.Base.Interface;
using FlexFlow.Model;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace FlexFlow.Runtime
{
    /// <summary>
    /// 表示本地磁盘物理文件管理器，用来提供对本地磁盘文件的读写操作
    /// </summary>
    public class LocalDiskFileProvider : IPhysicalFileProvider
    {
        /// <summary>
        /// 获取或设置用来储存物理文件的文件夹
        /// </summary>
        public static string PhysicalFileDir { get; set; }
        /// <summary>
        /// 根据指定的文件描述构造物理文件路径
        /// </summary>
        /// <param name="des">
        /// 要构建路径的文件描述
        /// </param>
        /// <returns>
        /// 构造的物理文件路径
        /// </returns>
        private string BuildFilePath(FileDescription des)
        {
            return PhysicalFileDir + "/" + des.Uploader.ToString() + "/" + des.Path + "/" + des.OutdateTime.Date.ToString("yyyy/MM/dd/") + "/";
        }

        /// <summary>
        /// 以读取方式打开文件
        /// </summary>
        /// <param name="des">
        /// 文件描述
        /// </param>
        /// <returns>
        /// 打开的文件流
        /// </returns>
        private Stream OpenForRead(FileDescription des)
        {
            string filePath = BuildFilePath(des);
            filePath += des.Identity.ToString();
            if (!File.Exists(filePath))
            {
                return null;
            }
            return File.OpenRead(filePath);
        }

        /// <summary>
        /// 以写入方式打开文件，若文件已存在，则清空文件内容
        /// </summary>
        /// <param name="des">
        /// 文件描述
        /// </param>
        /// <returns>
        /// 打开的文件流
        /// </returns>
        private Stream OpenForWrite(FileDescription des)
        {
            string filePath = BuildFilePath(des);
            if (!Directory.Exists(filePath))
            {
                Directory.CreateDirectory(filePath);
            }
            filePath += des.Identity;
            if (!File.Exists(filePath))
            {
                return File.Create(filePath);
            }
            return File.Open(filePath, FileMode.Truncate, FileAccess.Write, FileShare.None);
        }

        /// <summary>
        /// 从本地磁盘中打开指定文件
        /// </summary>
        /// <param name="des">
        /// 要打开的文件描述
        /// </param>
        /// <param name="mode">
        /// 打开方式
        /// </param>
        /// <returns>
        /// 用来读写操作的流，如果操作不成功，则返回null
        /// </returns>
        public Stream OpenFile(FileDescription des, FileOpenMode mode)
        {
            switch (mode)
            {
                case FileOpenMode.Read:
                    return OpenForRead(des);
                case FileOpenMode.Write:
                    return OpenForWrite(des);
                default:
                    return null;
            }
        }

        /// <summary>
        /// 初始化静态变量
        /// </summary>
        static LocalDiskFileProvider()
        {
            if (HttpContext.Current != null && HttpContext.Current.Server != null)
            {
                PhysicalFileDir = HttpContext.Current.Server.MapPath("~/") + "/UserData";
            }
            else
            {
                PhysicalFileDir = Environment.CurrentDirectory + "/UserData";
            }
        }

        /// <summary>
        /// 删除指定描述对应的物理文件
        /// </summary>
        /// <param name="des">
        /// 要删除的文件描述
        /// </param>
        /// <returns>
        /// 出错信息，如果删除文件成功，请返回空字符串，否则返回出错信息文本
        /// </returns>
        public string DeleteFile(FileDescription des)
        {
            string filePath = BuildFilePath(des);
            filePath += des.Identity.ToString();
            if (!File.Exists(filePath))
            {
                return "指定文件的物理文件已被删除！";
            }
            try
            {
                File.Delete(filePath);
                return string.Empty;
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        /// <summary>
        /// 判断指定文件描述对应的物理文件是否存在
        /// </summary>
        /// <param name="des">
        /// 要判断的文件描述
        /// </param>
        /// <returns>
        /// 一个表示物理文件是否存在的值
        /// </returns>
        public bool FileExists(FileDescription des)
        {
            string filePath = BuildFilePath(des);
            filePath += des.Identity.ToString();
            return File.Exists(filePath);
        }
    }
}
